/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.service.payment;

import net.martinimix.dao.payment.PaymentDao;
import net.martinimix.domain.order.Order;
import net.martinimix.domain.order.OrderHeader;
import net.martinimix.domain.payment.BillMeLaterAccount;
import net.martinimix.domain.payment.BillMeLaterAccountAuthorization;
import net.martinimix.domain.payment.Payment;
import net.martinimix.domain.payment.PaymentMethod;
import net.martinimix.service.account.CustomerService;
import net.martinimix.service.payment.provider.BillMeLaterProcessor;

/**
 * Provides a simple Bill Me Later payment service.
 * 
 * @author Scott Rossillo
 *
 */
public class BillMeLaterPaymentService implements PaymentService {

	private BillMeLaterProcessor billMeLaterProcessor;

	private String customerTermsAndConditionsVersion;
	
	private CustomerService customerService;
	private PaymentDao paymentDao;

	/**
	 * Creates a new simple Bill Me Later payment service.
	 */
	public BillMeLaterPaymentService() { }
	
	/**
	 * Authorizes the given Bill Me Later account.
	 * 
	 * @param billMeLaterAccount the <code>BillMeLaterAccount</code> to authorize
	 * @param order the <code>Order</code> for which payment should be authorized
	 * 
	 * @return an order <code>Payment</code> resulting from the authorization transaction
	 */
	public Payment authorizePayment(BillMeLaterAccount billMeLaterAccount, Order order) {
		
		BillMeLaterAccountAuthorization auth;
		Payment payment = order.findPayment(billMeLaterAccount);
		
		if(payment == null) {
			payment = this.createPayment(billMeLaterAccount, order.getOrderHeader());
			order.addPayment(payment);
		}
		
		billMeLaterAccount.setTermsAndConditionsVersion(customerTermsAndConditionsVersion);
		auth = billMeLaterProcessor.authorizePayment(billMeLaterAccount, order);
		
		auth.setPaymentId(payment.getId());
		
		if(auth.isPositiveResponse()) {
			payment.setStatusCode(Payment.STATUS_AUTHORIZED);
			billMeLaterAccount.setCardNumber(auth.getAccountNumber());
		} else {
			payment.setStatusCode(Payment.STATUS_INVALID);
		}
		
		customerService.saveBillMeLaterAccount(billMeLaterAccount, order.getCustomer());
		
		// saved BML account may have a new id (BM created)
		payment.setPaymentTypeId(billMeLaterAccount.getId());
		
		paymentDao.savePayment(payment);
		paymentDao.saveCreditCardTransaction(auth);
		
		return payment;
	}

	/* (non-Javadoc)
	 * @see net.martinimix.service.payment.PaymentService#authorizePayment(net.martinimix.domain.payment.PaymentMethod, net.martinimix.domain.order.Order)
	 */
	public final Payment authorizePayment(PaymentMethod paymentMethod, Order order) {
		return this.authorizePayment((BillMeLaterAccount) paymentMethod, order);
	}

	/* (non-Javadoc)
	 * @see net.martinimix.service.payment.PaymentService#createPayment(net.martinimix.domain.payment.PaymentMethod, net.martinimix.domain.order.OrderHeader)
	 */
	public Payment createPayment(PaymentMethod paymentMethod, OrderHeader orderHeader) {
		
		final Payment payment = new Payment();
		final BillMeLaterAccount billMeLaterAccount = (BillMeLaterAccount) paymentMethod;
		
		payment.setPaymentTypeId(billMeLaterAccount.getId());
		payment.setPaymentType(Payment.TYPE_CREDIT_CARD);
		payment.setStatusCode(Payment.STATUS_PENDING_AUTHORIZATION);
		payment.setOrderHeaderId(orderHeader.getId());		
		
		paymentDao.savePayment(payment);
		
		return payment;
	}
	
	/**
	 * Sets the customer terms and conditions version for this Bill Me Later payment service.
	 * 
	 * @param customerTermsAndConditionsVersion the terms and conditions version for this 
	 * payment service
	 */
	public void setCustomerTermsAndConditionsVersion(
			String customerTermsAndConditionsVersion) {
		this.customerTermsAndConditionsVersion = customerTermsAndConditionsVersion;
	}

	/**
	 * Sets the Bill Me Later processor for this payment service.
	 * 
	 * @param billMeLaterProcessor the <code>BillMeLaterProcessor</code>
	 * for this service
	 */
	public void setBillMeLaterProcessor(BillMeLaterProcessor billMeLaterProcessor) {
		this.billMeLaterProcessor = billMeLaterProcessor;
	}

	public void setCustomerService(CustomerService customerService) {
		this.customerService = customerService;
	}

	/**
	 * Sets the payment data access object for this service.
	 * 
	 * @param paymentDao the <code>PaymentDao</code> for this service
	 */
	public void setPaymentDao(PaymentDao paymentDao) {
		this.paymentDao = paymentDao;
	}

}
